﻿/*  Francis Nino Seisei 
 *  ©2012 Francis Antonio Bolaños Arias.
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Seisei.Berta.Generator
{
    public class CodeGenerator
    {

        /// <summary>
        /// Obtiene el string correspondiente al contenido de la plantilla BERTA.
        /// </summary>
        /// <param name="Template">Contenido del archivo de plantilla BERTA</param>
        /// <returns></returns>
        public static string Generate(string Template)
        {
            //Primero, vamos a ejecutar las etiquetas que no dependen de un ciclo de concatenación.
            Template = RUN_B_DEFINE_DATA_TYPES(Template);
            Template = RUN_B_2DEFINE_DATA_TYPES(Template);
            Template = RUN_B_3DEFINE_DATA_TYPES(Template);
            Template = RUN_B_4DEFINE_DATA_TYPES(Template);
            Template = RUN_B_5DEFINE_DATA_TYPES(Template);
            Template = RUN_B_DATABASE(Template);
            Template = RUN_B_DB_SERVER(Template);
            Template = RUN_B_DB_USER(Template);
            Template = RUN_B_DB_USER_PASS(Template);
            //Segundo, vamos a ejecutar los ciclos de concatenación
            Template = RUN_B_LOOP_DB(Template);
            Template = RUN_B_NULL(Template);
            return Template;
        }


        public static string RUN_B_DATABASE(string Template)
        {
            return Template.Replace("@B_DATABASE", Seisei.Nino.Reader.Parameters.DATABASE);
        }

        public static string RUN_B_DB_SERVER(string Template)
        {
            return Template.Replace("@B_DB_SERVER", Seisei.Nino.Reader.Parameters.DB_SERVER);
        }

        public static string RUN_B_DB_USER(string Template)
        {
            return Template.Replace("@B_DB_USER", Seisei.Nino.Reader.Parameters.DB_USER);
        }

        public static string RUN_B_DB_USER_PASS(string Template)
        {
            return Template.Replace("@B_DB_USER_PASS", Seisei.Nino.Reader.Parameters.DB_USER_PASS);
        }

        private static string RUN_B_LOOP_DB(string Template)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Template.Contains("@B_LOOP_DB"))
            {
                if (Template.Contains("@EB_LOOP_DB"))
                {

                    try
                    {
                        string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Template, "@B_LOOP_DB", "@EB_LOOP_DB");
                        //Se procede a reemplazar el ciclo por el respectivo código generado
                        Template = Template.Replace("@B_LOOP_DB" + SubTemplate + "@EB_LOOP_DB"
                            , RUN_B_LOOP_DB_PART(SubTemplate));
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ RUN_B_LOOP_DB:\r\n" + Template);
                    }
                }
                else
                {
                    throw new BertaNonEndingLoopException("Loop de base de datos sin final [@EB_LOOP_DB]:\r\n" + Template);
                }
            }
            return Template;
        }

        public static string RUN_B_LOOP_DB_PART(string Part)
        {
            string Code = "";
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_LOOP_DB"))
            {
                if (Part.Contains("@EB_LOOP_DB"))
                {
                    Part = RUN_B_LOOP_DB(Part);
                }
                else
                {
                    throw new BertaNonEndingLoopException("Loop de base de datos sin final [@EB_LOOP_DB]:\r\n" + Part);
                }
            }

            //Comienza la concatenación en base al ciclo sobre las tablas de bases de datos y sustitución de etiquetas
            //del ciclo de base de datos.
            string RetCode = "";
            foreach (Seisei.Nino.Reader.Table tabla in Seisei.Nino.Reader.Database.DataMatrix)
            {
                Code = Part.Replace("@B_TABLENAME", tabla.Name);

                if (Code.Contains("@B_PRIMARY_CODE"))
                {
                    Code = RUN_B_PRIMARY_CODE(Code, tabla);
                }
                if (Code.Contains("@B_IDENTITY_CODE"))
                {
                    Code = RUN_B_IDENTITY_CODE(Code, tabla);
                }
                if (Code.Contains("@B_FOREIGN_CODE"))
                {
                    Code = RUN_B_FOREIGN_CODE(Code, tabla);
                }
                if (Code.Contains("@B_LOOP_TABLE_NON_PRIMARY"))
                {
                    Code = RUN_B_LOOP_TABLE_NON_PRIMARY(Code, tabla);
                }
                if (Code.Contains("@B_LOOP_TABLE_PRIMARY_OR_ALL"))
                {
                    Code = RUN_B_LOOP_TABLE_PRIMARY_OR_ALL(Code, tabla);
                }
                if (Code.Contains("@B_LOOP_TABLE_PRIMARY_OR_FIRST"))
                {
                    Code = RUN_B_LOOP_TABLE_PRIMARY_OR_FIRST(Code, tabla);
                }
                if (Code.Contains("@B_LOOP_TABLES_RELATIONED"))
                {
                    Code = RUN_B_LOOP_TABLES_RELATIONED(Code, tabla);
                }
                if (Code.Contains("@B_LOOP_TABLE"))
                {
                    Code = RUN_B_LOOP_TABLE(Code, tabla);
                }
                if (Code.Contains("@B_HAVE_FOREIGN_OUT"))
                {
                    Code = RUN_B_HAVE_FOREIGN_OUT(Code, tabla);
                }
                if (Code.Contains("@B_HAVE_PRIMARY"))
                {
                    Code = RUN_B_HAVE_PRIMARY(Code, tabla);
                }
                if (Code.Contains("@B_HAVE_IDENTITY"))
                {
                    Code = RUN_B_HAVE_IDENTITY(Code, tabla);
                }
                if (Code.Contains("@B_HAVE_FOREIGN"))
                {
                    Code = RUN_B_HAVE_FOREIGN(Code, tabla);
                }
                RetCode += Code;
            }
            return RetCode;
        }

        private static string RUN_B_LOOP_TABLE(string Template, Seisei.Nino.Reader.Table Tabla)
        {

            //Verificar que tenga la etiqueta de inicio y final
            while (Template.Contains("@B_LOOP_TABLE"))
            {
                if (Template.Contains("@EB_LOOP_TABLE"))
                {
                    try
                    {
                        string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Template, "@B_LOOP_TABLE", "@EB_LOOP_TABLE");
                        string Aux = SubTemplate;
                        //Quitar parámetros del B_LOOP_TABLE si los tiene
                        //Se concatena al final de cada iteración de las columnas
                        string LS = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(SubTemplate, "[@B]", "[@EB]");
                        if (LS.Length > 0)
                        {
                            SubTemplate = SubTemplate.Replace("[@B]" + LS + "[@EB]", "");
                        }
                        //Se procede a reemplazar el ciclo por el respectivo código generado
                        Template = Template.Replace("@B_LOOP_TABLE" + Aux + "@EB_LOOP_TABLE"
                            , RUN_B_LOOP_TABLE_PART(SubTemplate, Tabla, LS));
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ RUN_B_LOOP_TABLE:\r\n" + Template);
                    }
                }
                else
                {
                    throw new BertaNonEndingLoopException("Ciclo de tabla sin final [@EB_LOOP_TABLE]:\r\n" + Template);
                }
            }
            return Template;
        }

        private static string RUN_B_LOOP_TABLES_RELATIONED(string Template, Seisei.Nino.Reader.Table Tabla)
        {

            //Verificar que tenga la etiqueta de inicio y final
            while (Template.Contains("@B_LOOP_TABLES_RELATIONED"))
            {
                if (Template.Contains("@EB_LOOP_TABLES_RELATIONED"))
                {
                    try
                    {
                        string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Template, "@B_LOOP_TABLES_RELATIONED", "@EB_LOOP_TABLES_RELATIONED");
                        string Aux = SubTemplate;
                        //Quitar parámetros del B_LOOP_TABLE si los tiene
                        //Se concatena al final de cada iteración de las columnas
                        string LS = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(SubTemplate, "[@B]", "[@EB]");
                        if (LS.Length > 0)
                        {
                            SubTemplate = SubTemplate.Replace("[@B]" + LS + "[@EB]", "");
                        }
                        //Se procede a reemplazar el ciclo por el respectivo código generado
                        Template = Template.Replace("@B_LOOP_TABLES_RELATIONED" + Aux + "@EB_LOOP_TABLES_RELATIONED"
                            , RUN_B_LOOP_TABLES_RELATIONED_PART(SubTemplate, Tabla, LS));
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ RUN_B_LOOP_TABLES_RELATIONED:\r\n" + Template);
                    }
                }
                else
                {
                    throw new BertaNonEndingLoopException("Ciclo de tabla sin final [@EB_LOOP_TABLES_RELATIONED]:\r\n" + Template);
                }
            }
            return Template;
        }

        private static string RUN_B_LOOP_TABLE_PRIMARY_OR_ALL(string Template, Seisei.Nino.Reader.Table Tabla)
        {

            //Verificar que tenga la etiqueta de inicio y final
            while (Template.Contains("@B_LOOP_TABLE_PRIMARY_OR_ALL"))
            {
                if (Template.Contains("@EB_LOOP_TABLE_PRIMARY_OR_ALL"))
                {
                    try
                    {
                        string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Template, "@B_LOOP_TABLE_PRIMARY_OR_ALL", "@EB_LOOP_TABLE_PRIMARY_OR_ALL");
                        string Aux = SubTemplate;
                        //Quitar parámetros del B_LOOP_TABLE si los tiene
                        //Se concatena al final de cada iteración de las columnas
                        string LS = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(SubTemplate, "[@B]", "[@EB]");
                        if (LS.Length > 0)
                        {
                            SubTemplate = SubTemplate.Replace("[@B]" + LS + "[@EB]", "");
                        }
                        //Se procede a reemplazar el ciclo por el respectivo código generado
                        Template = Template.Replace("@B_LOOP_TABLE_PRIMARY_OR_ALL" + Aux + "@EB_LOOP_TABLE_PRIMARY_OR_ALL"
                            , RUN_B_LOOP_TABLE_PRIMARY_OR_ALL_PART(SubTemplate, Tabla, LS));
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_LOOP_TABLE_PRIMARY_OR_ALL:\r\n" + Template);
                    }
                }
                else
                {
                    throw new BertaNonEndingLoopException("Ciclo de tabla sin final [@EB_LOOP_TABLE_PRIMARY_OR_ALL]:\r\n" + Template);
                }
            }
            return Template;
        }

        private static string RUN_B_LOOP_TABLE_PRIMARY_OR_FIRST(string Template, Seisei.Nino.Reader.Table Tabla)
        {

            //Verificar que tenga la etiqueta de inicio y final
            while (Template.Contains("@B_LOOP_TABLE_PRIMARY_OR_FIRST"))
            {
                if (Template.Contains("@EB_LOOP_TABLE_PRIMARY_OR_FIRST"))
                {
                    try
                    {
                        string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Template, "@B_LOOP_TABLE_PRIMARY_OR_FIRST", "@EB_LOOP_TABLE_PRIMARY_OR_FIRST");
                        string Aux = SubTemplate;
                        //Quitar parámetros del B_LOOP_TABLE si los tiene
                        //Se concatena al final de cada iteración de las columnas
                        string LS = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(SubTemplate, "[@B]", "[@EB]");
                        if (LS.Length > 0)
                        {
                            SubTemplate = SubTemplate.Replace("[@B]" + LS + "[@EB]", "");
                        }
                        //Se procede a reemplazar el ciclo por el respectivo código generado
                        Template = Template.Replace("@B_LOOP_TABLE_PRIMARY_OR_FIRST" + Aux + "@EB_LOOP_TABLE_PRIMARY_OR_FIRST"
                            , RUN_B_LOOP_TABLE_PRIMARY_OR_FIRST_PART(SubTemplate, Tabla, LS));
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_LOOP_TABLE_PRIMARY_OR_FIRST:\r\n" + Template);
                    }
                }
                else
                {
                    throw new BertaNonEndingLoopException("Ciclo de tabla sin final [@EB_LOOP_TABLE_PRIMARY_OR_FIRST]:\r\n" + Template);
                }
            }
            return Template;
        }

        public static string RUN_B_LOOP_TABLES_RELATIONED_PART(string Part, Seisei.Nino.Reader.Table Tabla, string LineSeparator)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_LOOP_TABLES_RELATIONED"))
            {
                if (Part.Contains("@EB_LOOP_TABLES_RELATIONED"))
                {
                    Part = RUN_B_LOOP_TABLES_RELATIONED(Part, Tabla);
                }
                else
                {
                    throw new BertaNonEndingLoopException("Loop de tabla sin final [@EB_LOOP_TABLES_RELATIONED]:\r\n" + Part);
                }
            }
            //Comienza la concatenación en base al ciclo sobre las tablas de bases de datos y sustitución de etiquetas
            //del ciclo de base de datos.
            string RetCode = "";
            string Code = "";
            int j = 0;
            Seisei.Nino.Reader.Column ColPrimaria = new Seisei.Nino.Reader.Column();
            bool IhavePrimary = false;
            foreach (Seisei.Nino.Reader.Column columna in Tabla.Columns) {
                if (columna.Primary) {
                    ColPrimaria = columna;
                    IhavePrimary = true;
                }
            }
            foreach (Seisei.Nino.Reader.Table tbl in Seisei.Nino.Reader.Database.DataMatrix)
            {
                if (!tbl.Name.Equals(Tabla.Name))
                {
                    foreach (Seisei.Nino.Reader.Column col in tbl.Columns)
                    {
                        if (col.ForeignTable.Equals(Tabla.Name))
                        {
                            Code = Part;
                            Code = RUN_B_FOREIGN_TABLE_COLNAME(Code, col);
                            Code = RUN_B_FOREIGN_TABLE(Code, tbl);
                            if (IhavePrimary)
                            {
                                RetCode += RUN_LOOP_TABLE_INTERNAL_LABELS(Code, j, ColPrimaria, Tabla) + LineSeparator;
                            }
                            else 
                            {
                                RetCode += RUN_LOOP_TABLE_INTERNAL_LABELS(Code, j, col, Tabla) + LineSeparator;
                            }
                            j++;
                        }
                    }
                }
            }
            try
            {
                RetCode = RetCode.Remove(RetCode.Length - LineSeparator.Length);
            }
            catch (ArgumentOutOfRangeException) { }
            return RetCode;
        }

        public static string RUN_B_LOOP_TABLE_PART(string Part, Seisei.Nino.Reader.Table Tabla, string LineSeparator)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_LOOP_TABLE"))
            {
                if (Part.Contains("@EB_LOOP_TABLE"))
                {
                    Part = RUN_B_LOOP_TABLE(Part, Tabla);
                }
                else
                {
                    throw new BertaNonEndingLoopException("Loop de tabla sin final [@EB_LOOP_TABLE]:\r\n" + Part);
                }
            }
            //Comienza la concatenación en base al ciclo sobre las tablas de bases de datos y sustitución de etiquetas
            //del ciclo de base de datos.
            string RetCode = "";
            string Code = "";
            int j = 0;
            foreach (Seisei.Nino.Reader.Column columna in Tabla.Columns)
            {
                Code = Part;
                RetCode += RUN_LOOP_TABLE_INTERNAL_LABELS(Code, j, columna, Tabla) + LineSeparator;
                j++;
            }
            return RetCode.Remove(RetCode.Length - LineSeparator.Length);
        }

        public static string RUN_B_LOOP_TABLE_PRIMARY_OR_ALL_PART(string Part, Seisei.Nino.Reader.Table Tabla, string LineSeparator)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_LOOP_TABLE_PRIMARY_OR_ALL"))
            {
                if (Part.Contains("@EB_LOOP_TABLE_PRIMARY_OR_ALL"))
                {
                    Part = RUN_B_LOOP_TABLE_PRIMARY_OR_ALL(Part, Tabla);
                }
                else
                {
                    throw new BertaNonEndingLoopException("Loop de tabla sin final [@EB_LOOP_TABLE_PRIMARY_OR_ALL]:\r\n" + Part);
                }
            }
            //Comienza la concatenación en base al ciclo sobre las tablas de bases de datos y sustitución de etiquetas
            //del ciclo de base de datos.
            string RetCode = "";
            string Code = "";
            bool havePrimary = false;
            int i = 0;
            foreach (Seisei.Nino.Reader.Column columna in Tabla.Columns)
            {
                if (columna.Primary)
                {
                    Code = Part;
                    RetCode += RUN_LOOP_TABLE_INTERNAL_LABELS(Code, i, columna, Tabla) + LineSeparator;
                    havePrimary = true;
                    i++;
                }
            }
            if (!havePrimary)
            {
                int j = 0;
                foreach (Seisei.Nino.Reader.Column columna in Tabla.Columns)
                {
                    Code = Part;
                    RetCode += RUN_LOOP_TABLE_INTERNAL_LABELS(Code, j, columna, Tabla) + LineSeparator;
                    havePrimary = true;
                    j++;
                }
            }
            return RetCode.Remove(RetCode.Length - LineSeparator.Length);
        }

        public static string RUN_B_LOOP_TABLE_PRIMARY_OR_FIRST_PART(string Part, Seisei.Nino.Reader.Table Tabla, string LineSeparator)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_LOOP_TABLE_PRIMARY_OR_FIRST"))
            {
                if (Part.Contains("@EB_LOOP_TABLE_PRIMARY_OR_FIRST"))
                {
                    Part = RUN_B_LOOP_TABLE_PRIMARY_OR_FIRST(Part, Tabla);
                }
                else
                {
                    throw new BertaNonEndingLoopException("Loop de tabla sin final [@EB_LOOP_TABLE_PRIMARY_OR_FIRST]:\r\n" + Part);
                }
            }
            //Comienza la concatenación en base al ciclo sobre las tablas de bases de datos y sustitución de etiquetas
            //del ciclo de base de datos.
            string RetCode = "";
            string Code = "";
            bool havePrimary = false;
            int i = 0;
            foreach (Seisei.Nino.Reader.Column columna in Tabla.Columns)
            {
                if (columna.Primary)
                {
                    Code = Part;
                    RetCode += RUN_LOOP_TABLE_INTERNAL_LABELS(Code, i, columna, Tabla) + LineSeparator;
                    havePrimary = true;
                    i++;
                }
            }
            if (!havePrimary)
            {
                int j = 0;
                foreach (Seisei.Nino.Reader.Column columna in Tabla.Columns)
                {
                    if (j < 1)
                    {
                        Code = Part;
                        RetCode += RUN_LOOP_TABLE_INTERNAL_LABELS(Code, j, columna, Tabla) + LineSeparator;
                        havePrimary = true;
                        j++;
                    }
                }
            }
            return RetCode.Remove(RetCode.Length - LineSeparator.Length);
        }

        private static string RUN_B_LOOP_TABLE_NON_PRIMARY(string Template, Seisei.Nino.Reader.Table Tabla)
        {

            //Verificar que tenga la etiqueta de inicio y final
            while (Template.Contains("@B_LOOP_TABLE_NON_PRIMARY"))
            {
                if (Template.Contains("@EB_LOOP_TABLE_NON_PRIMARY"))
                {
                    try
                    {
                        string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Template, "@B_LOOP_TABLE_NON_PRIMARY", "@EB_LOOP_TABLE_NON_PRIMARY");
                        string Aux = SubTemplate;
                        //Quitar parámetros del B_LOOP_TABLE si los tiene
                        //Se concatena al final de cada iteración de las columnas
                        string LS = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(SubTemplate, "[@B]", "[@EB]");
                        if (LS.Length > 0)
                        {
                            SubTemplate = SubTemplate.Replace("[@B]" + LS + "[@EB]", "");
                        }
                        //Se procede a reemplazar el ciclo por el respectivo código generado
                        Template = Template.Replace("@B_LOOP_TABLE_NON_PRIMARY" + Aux + "@EB_LOOP_TABLE_NON_PRIMARY"
                            , RUN_B_LOOP_TABLE_NON_PRIMARY_PART(SubTemplate, Tabla, LS));
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_LOOP_TABLE_NON_PRIMARY:\r\n" + Template);
                    }
                }
                else
                {
                    throw new BertaNonEndingLoopException("Ciclo de tabla sin final [@EB_LOOP_TABLE_NON_PRIMARY]:\r\n" + Template);
                }
            }
            return Template;
        }

        public static string RUN_B_LOOP_TABLE_NON_PRIMARY_PART(string Part, Seisei.Nino.Reader.Table Tabla, string LineSeparator)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_LOOP_TABLE_NON_PRIMARY"))
            {
                if (Part.Contains("@EB_LOOP_TABLE_NON_PRIMARY"))
                {
                    Part = RUN_B_LOOP_TABLE(Part, Tabla);
                }
                else
                {
                    throw new BertaNonEndingLoopException("Loop de tabla sin final [@EB_LOOP_TABLE_NON_PRIMARY]:\r\n" + Part);
                }
            }
            //Comienza la concatenación en base al ciclo sobre las tablas de bases de datos y sustitución de etiquetas
            //del ciclo de base de datos.
            string RetCode = "";
            string Code = "";
            int j = 0;
            foreach (Seisei.Nino.Reader.Column columna in Tabla.Columns)
            {
                if (!columna.Primary)
                {
                    Code = Part;
                    RetCode += RUN_LOOP_TABLE_INTERNAL_LABELS(Code, j, columna, Tabla) + LineSeparator;
                    j++;
                }
            }
            return RetCode.Remove(RetCode.Length - LineSeparator.Length);
        }

        private static string RUN_B_FOREIGN_TABLE_COLNAME(string Part, Seisei.Nino.Reader.Column Columna)
        {
            return Part.Replace("@B_FOREIGN_TABLE_COLNAME", Columna.Name);
        }

        private static string RUN_B_FOREIGN_TABLE(string Part, Seisei.Nino.Reader.Table Tabla)
        {
            return Part.Replace("@B_FOREIGN_TABLE", Tabla.Name);
        }

        private static string RUN_B_COLNAME(string Part, Seisei.Nino.Reader.Column Columna)
        {
            return Part.Replace("@B_COLNAME", Columna.Name);
        }

        private static string RUN_B_DATATYPE(string Part, string DataType)
        {
            return Part.Replace("@B_DATATYPE", DataType);
        }

        private static string RUN_B_2DATATYPE(string Part, string DataType)
        {
            return Part.Replace("@B_2DATATYPE", Global.DataTypes.GetDataType(2, DataType));
        }

        private static string RUN_B_3DATATYPE(string Part, string DataType)
        {
            return Part.Replace("@B_3DATATYPE", Global.DataTypes.GetDataType(3, DataType));
        }

        private static string RUN_B_4DATATYPE(string Part, string DataType)
        {
            return Part.Replace("@B_4DATATYPE", Global.DataTypes.GetDataType(4, DataType));
        }

        private static string RUN_B_5DATATYPE(string Part, string DataType)
        {
            return Part.Replace("@B_5DATATYPE", Global.DataTypes.GetDataType(5, DataType));
        }

        private static string RUN_B_NINO_DATATYPE(string Part, string DataType)
        {
            return Part.Replace("@B_NINO_DATATYPE", DataType);
        }

        private static string RUN_B_NULL(string Part)
        {
            return Part.Replace("@B_NULL", "");
        }

        private static string RUN_B_ITERATION(string Part, int Iteration)
        {
            return Part.Replace("@B_ITERATION", Iteration.ToString());
        }

        private static string RUN_B_DATALENGTH(string Part, int DataLength)
        {
            return Part.Replace("@B_DATALENGTH", DataLength.ToString());
        }

        private static string INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(string Template, string StartLabel, string EndLabel)
        {
            //Donde inicia el contenido de la plantilla que está adentro del ciclo.
            int b = Template.IndexOf(StartLabel) + StartLabel.Length;
            //Definirá donde acaba el contenido de la plantilla del ciclo.
            int e = 0;
            for (int i = b; i < Template.Length; i++)
            {
                string dbg = Template.Substring(i, EndLabel.Length);
                if (Template.Substring(i, EndLabel.Length).Equals(EndLabel))
                {
                    //Obtenemos el final
                    e = i;
                    if (b != e)
                    {
                        return Template.Substring(b, e - b);
                    }
                    else
                    {
                        //No hay contenido para hacer el ciclo
                        throw new BertaNonContentLoopException("ERROR: Las etiquetas " + StartLabel + " y " + EndLabel + " no tienen contenido. Sin no llevan contenido puede solucionarlo poniendo la etiqueta @B_NULL @INTERNAL_GET_SUBSTRING_BETWEEN_LABELS:\r\n" + Template);
                    }
                }
            }
            return "";
        }

        private static string RUN_B_IS_PRIMARY(string Part, Seisei.Nino.Reader.Table tabla, string ColumnName)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_IS_PRIMARY"))
            {
                try
                {
                    string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_IS_PRIMARY[@B]", "[@EB]");
                    string IsPrimary = "";
                    string NotPrimary = "";
                    if (SubTemplate.Length > 0)
                    {
                        string[] aux = SubTemplate.Split('|');
                        try
                        {
                            if (aux.Length == 2)
                            {
                                IsPrimary = aux[0];
                                NotPrimary = aux[1];
                            }
                            else
                            {
                                throw new BertaNeedsParametersException("Solo se permiten 2 parámetros la instrucción @B_IS_PRIMARY:\r\n" + Part);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        {
                            throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_IS_PRIMARY:\r\n" + Part);
                        }
                        string Code = "";
                        foreach (Seisei.Nino.Reader.Column col in tabla.Columns)
                        {
                            if (col.Name.Equals(ColumnName))
                            {
                                if (col.Primary)
                                {
                                    Code = Part.Replace("@B_IS_PRIMARY[@B]" + IsPrimary + "|" + NotPrimary + "[@EB]", IsPrimary);
                                }
                                else
                                {
                                    Code = Part.Replace("@B_IS_PRIMARY[@B]" + IsPrimary + "|" + NotPrimary + "[@EB]", NotPrimary);
                                }
                                return Code;
                            }
                        }
                    }
                    else
                    {
                        throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_IS_PRIMARY:\r\n" + Part);
                    }

                }
                catch (IndexOutOfRangeException)
                {
                    throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_IS_PRIMARY:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_IS_IDENTITY(string Part, Seisei.Nino.Reader.Table tabla, string ColumnName)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_IS_IDENTITY"))
            {
                try
                {
                    string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_IS_IDENTITY[@B]", "[@EB]");
                    string IsIdentity = "";
                    string NotIdentity = "";
                    if (SubTemplate.Length > 0)
                    {
                        string[] aux = SubTemplate.Split('|');
                        try
                        {
                            if (aux.Length == 2)
                            {
                                IsIdentity = aux[0];
                                NotIdentity = aux[1];
                            }
                            else
                            {
                                throw new BertaNeedsParametersException("Solo se permiten 2 parámetros la instrucción @B_IS_IDENTITY:\r\n" + Part);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        {
                            throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_IS_IDENTITY:\r\n" + Part);
                        }
                        string Code = "";
                        foreach (Seisei.Nino.Reader.Column col in tabla.Columns)
                        {
                            if (col.Name.Equals(ColumnName))
                            {
                                if (col.Identity)
                                {
                                    Code = Part.Replace("@B_IS_IDENTITY[@B]" + IsIdentity + "|" + NotIdentity + "[@EB]", IsIdentity);
                                }
                                else
                                {
                                    Code = Part.Replace("@B_IS_IDENTITY[@B]" + IsIdentity + "|" + NotIdentity + "[@EB]", NotIdentity);
                                }
                                return Code;
                            }
                        }
                    }
                    else
                    {
                        throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_IS_IDENTITY:\r\n" + Part);
                    }

                }
                catch (IndexOutOfRangeException)
                {
                    throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_IS_IDENTITY:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_IS_FOREIGN(string Part, Seisei.Nino.Reader.Table tabla, string ColumnName)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_IS_FOREIGN"))
            {
                try
                {
                    string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_IS_FOREIGN[@B]", "[@EB]");
                    string IsForeign = "";
                    string NotForeign = "";
                    if (SubTemplate.Length > 0)
                    {
                        string[] aux = SubTemplate.Split('|');
                        try
                        {
                            if (aux.Length == 2)
                            {
                                IsForeign = aux[0];
                                NotForeign = aux[1];
                            }
                            else
                            {
                                throw new BertaNeedsParametersException("Solo se permiten 2 parámetros la instrucción @B_IS_FOREIGN:\r\n" + Part);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        {
                            throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_IS_FOREIGN:\r\n" + Part);
                        }
                        string Code = "";
                        foreach (Seisei.Nino.Reader.Column col in tabla.Columns)
                        {
                            if (col.Name.Equals(ColumnName))
                            {
                                if (col.Foreign)
                                {
                                    Code = Part.Replace("@B_IS_FOREIGN[@B]" + IsForeign + "|" + NotForeign + "[@EB]", IsForeign);
                                }
                                else
                                {
                                    Code = Part.Replace("@B_IS_FOREIGN[@B]" + IsForeign + "|" + NotForeign + "[@EB]", NotForeign);
                                }
                                return Code;
                            }
                        }
                    }
                    else
                    {
                        throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_IS_FOREIGN:\r\n" + Part);
                    }

                }
                catch (IndexOutOfRangeException)
                {
                    throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_IS_FOREIGN:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_HAVE_PRIMARY(string Part, Seisei.Nino.Reader.Table tabla)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_HAVE_PRIMARY"))
            {
                try
                {
                    string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_HAVE_PRIMARY[@B]", "[@EB]");
                    string HavePrimary = "";
                    string NotPrimary = "";
                    if (SubTemplate.Length > 0)
                    {
                        string[] aux = SubTemplate.Split('|');
                        try
                        {
                            if (aux.Length == 2)
                            {
                                HavePrimary = aux[0];
                                NotPrimary = aux[1];
                            }
                            else
                            {
                                throw new BertaNeedsParametersException("Solo se permiten 2 parámetros la instrucción @B_HAVE_PRIMARY:\r\n" + Part);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        {
                            throw new BertaNeedsParametersException("ERROR: IndexOutOfRangeException @ B_HAVE_PRIMARY:\r\n" + Part);
                        }
                        string Code = "";
                        bool haveAPrimary = false;
                        int j = 0;
                        foreach (Seisei.Nino.Reader.Column col in tabla.Columns)
                        {
                            if (j == 0)
                            {
                                if (col.Primary)
                                {
                                    Code = Part.Replace("@B_HAVE_PRIMARY[@B]" + HavePrimary + "|" + NotPrimary + "[@EB]", HavePrimary);
                                    haveAPrimary = true;
                                    j++;
                                }
                            }
                        }
                        if (!haveAPrimary)
                        {
                            Code = Part.Replace("@B_HAVE_PRIMARY[@B]" + HavePrimary + "|" + NotPrimary + "[@EB]", NotPrimary);
                        }
                        Part = Code;
                    }
                    else
                    {
                        throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_HAVE_PRIMARY:\r\n" + Part);
                    }

                }
                catch (IndexOutOfRangeException)
                {
                    throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_HAVE_PRIMARY:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_HAVE_IDENTITY(string Part, Seisei.Nino.Reader.Table tabla)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_HAVE_IDENTITY"))
            {
                try
                {
                    string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_HAVE_IDENTITY[@B]", "[@EB]");
                    string HaveIdentity = "";
                    string NotIdentity = "";
                    if (SubTemplate.Length > 0)
                    {
                        string[] aux = SubTemplate.Split('|');
                        try
                        {
                            if (aux.Length == 2)
                            {
                                HaveIdentity = aux[0];
                                NotIdentity = aux[1];
                            }
                            else
                            {
                                throw new BertaNeedsParametersException("Solo se permiten 2 parámetros la instrucción @B_HAVE_IDENTITY:\r\n" + Part);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        {
                            throw new BertaNeedsParametersException("ERROR: IndexOutOfRangeException @ B_HAVE_IDENTITY:\r\n" + Part);
                        }
                        string Code = "";
                        bool haveAIdentity = false;
                        int j = 0;
                        foreach (Seisei.Nino.Reader.Column col in tabla.Columns)
                        {
                            if (j == 0)
                            {
                                if (col.Identity)
                                {
                                    Code = Part.Replace("@B_HAVE_IDENTITY[@B]" + HaveIdentity + "|" + NotIdentity + "[@EB]", HaveIdentity);
                                    haveAIdentity = true;
                                    j++;
                                }
                            }
                        }
                        if (!haveAIdentity)
                        {
                            Code = Part.Replace("@B_HAVE_IDENTITY[@B]" + HaveIdentity + "|" + NotIdentity + "[@EB]", NotIdentity);
                        }
                        Part = Code;
                    }
                    else
                    {
                        throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_HAVE_IDENTITY:\r\n" + Part);
                    }

                }
                catch (IndexOutOfRangeException)
                {
                    throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_HAVE_IDENTITY:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_HAVE_FOREIGN(string Part, Seisei.Nino.Reader.Table tabla)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_HAVE_FOREIGN"))
            {
                try
                {
                    string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_HAVE_FOREIGN[@B]", "[@EB]");
                    string HaveForeign = "";
                    string NotForeign = "";
                    if (SubTemplate.Length > 0)
                    {
                        string[] aux = SubTemplate.Split('|');
                        try
                        {
                            if (aux.Length == 2)
                            {
                                HaveForeign = aux[0];
                                NotForeign = aux[1];
                            }
                            else
                            {
                                throw new BertaNeedsParametersException("Solo se permiten 2 parámetros la instrucción @B_HAVE_FOREIGN:\r\n" + Part);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        {
                            throw new BertaNeedsParametersException("ERROR: IndexOutOfRangeException @ B_HAVE_FOREIGN:\r\n" + Part);
                        }
                        string Code = "";
                        bool haveAForeign = false;
                        int j = 0;
                        foreach (Seisei.Nino.Reader.Column col in tabla.Columns)
                        {
                            if (j == 0)
                            {
                                if (col.Foreign)
                                {
                                    Code = Part.Replace("@B_HAVE_FOREIGN[@B]" + HaveForeign + "|" + NotForeign + "[@EB]", HaveForeign);
                                    haveAForeign = true;
                                    j++;
                                }
                            }
                        }
                        if (!haveAForeign)
                        {
                            Code = Part.Replace("@B_HAVE_FOREIGN[@B]" + HaveForeign + "|" + NotForeign + "[@EB]", NotForeign);
                        }
                        Part = Code;
                    }
                    else
                    {
                        throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_HAVE_FOREIGN:\r\n" + Part);
                    }

                }
                catch (IndexOutOfRangeException)
                {
                    throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_HAVE_FOREIGN:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_HAVE_FOREIGN_OUT(string Part, Seisei.Nino.Reader.Table tabla)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_HAVE_FOREIGN_OUT"))
            {
                try
                {
                    string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_HAVE_FOREIGN_OUT[@B]", "[@EB]");
                    string HaveForeign = "";
                    string NotForeign = "";
                    if (SubTemplate.Length > 0)
                    {
                        string[] aux = SubTemplate.Split('|');
                        try
                        {
                            if (aux.Length == 2)
                            {
                                HaveForeign = aux[0];
                                NotForeign = aux[1];
                            }
                            else
                            {
                                throw new BertaNeedsParametersException("Solo se permiten 2 parámetros la instrucción @B_HAVE_FOREIGN_OUT:\r\n" + Part);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        {
                            throw new BertaNeedsParametersException("ERROR: IndexOutOfRangeException @ B_HAVE_FOREIGN_OUT:\r\n" + Part);
                        }
                        string Code = "";
                        bool haveAForeign = false;
                        int j = 0;
                        foreach (Seisei.Nino.Reader.Table tbl in Seisei.Nino.Reader.Database.DataMatrix)
                        {
                            if (j == 0)
                            {
                                if (!tbl.Name.Equals(tabla.Name))
                                {
                                    foreach (Seisei.Nino.Reader.Column col in tbl.Columns)
                                    {
                                        if (col.ForeignTable.Equals(tabla.Name))
                                        {
                                            Code = Part.Replace("@B_HAVE_FOREIGN_OUT[@B]" + HaveForeign + "|" + NotForeign + "[@EB]", HaveForeign);
                                            haveAForeign = true;
                                            j++;
                                        }
                                    }
                                }
                            }
                        }
                        if (!haveAForeign)
                        {
                            Code = Part.Replace("@B_HAVE_FOREIGN_OUT[@B]" + HaveForeign + "|" + NotForeign + "[@EB]", NotForeign);
                        }
                        Part = Code;
                    }
                    else
                    {
                        throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_HAVE_FOREIGN_OUT:\r\n" + Part);
                    }

                }
                catch (IndexOutOfRangeException)
                {
                    throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_HAVE_FOREIGN_OUT:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_HAVE_DATALENGTH(string Part, Seisei.Nino.Reader.Column columna)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_HAVE_DATALENGTH"))
            {
                try
                {
                    string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_HAVE_DATALENGTH[@B]", "[@EB]");
                    string HaveLength = "";
                    string NotLength = "";
                    if (SubTemplate.Length > 0)
                    {
                        string[] aux = SubTemplate.Split('|');
                        try
                        {
                            if (aux.Length == 2)
                            {
                                HaveLength = aux[0];
                                NotLength = aux[1];
                            }
                            else
                            {
                                throw new BertaNeedsParametersException("Solo se permiten 2 parámetros la instrucción @B_HAVE_DATALENGTH:\r\n" + Part);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        {
                            throw new BertaNeedsParametersException("ERROR: IndexOutOfRangeException @ B_HAVE_DATALENGTH:\r\n" + Part);
                        }
                        string Code = "";
                        //bool haveADataLength = false;
                        int j = 0;
                        //foreach (Seisei.Nino.Reader.Column col in tabla.Columns)
                        //{
                            //if (j == 0)
                            //{
                                if (columna.DataLength != -1)
                                {
                                    Code = Part.Replace("@B_HAVE_DATALENGTH[@B]" + HaveLength + "|" + NotLength + "[@EB]", RUN_B_DATALENGTH(HaveLength, columna.DataLength));
                                    //haveADataLength = true;
                                    //j++;
                                }
                                else {
                                    Code = Part.Replace("@B_HAVE_DATALENGTH[@B]" + HaveLength + "|" + NotLength + "[@EB]", NotLength);
                                }
                                j++;
                            //}
                        //}
                        //if (!haveADataLength)
                        //{
                        //    Code = Part.Replace("@B_HAVE_DATALENGTH[@B]" + HaveLength + "|" + NotLength + "[@EB]", NotLength);
                        //}
                        Part = Code;
                    }
                    else
                    {
                        throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_HAVE_DATALENGTH:\r\n" + Part);
                    }

                }
                catch (IndexOutOfRangeException)
                {
                    throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_HAVE_DATALENGTH:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_IS_NULL(string Part, Seisei.Nino.Reader.Table tabla, string ColumnName)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_IS_NULL"))
            {
                try
                {
                    string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "[@B]", "[@EB]");
                    string IsNullable = "";
                    string NotNullable = "";
                    if (SubTemplate.Length > 0)
                    {
                        string[] aux = SubTemplate.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                        try
                        {
                            if (aux.Length == 2)
                            {
                                IsNullable = aux[0];
                                NotNullable = aux[1];
                            }
                            else
                            {
                                throw new BertaNeedsParametersException("Solo se permiten 2 parámetros la instrucción @B_IS_NULL:\r\n" + Part);
                            }
                        }
                        catch (IndexOutOfRangeException)
                        {
                            throw new BertaNeedsParametersException("ERROR: IndexOutOfRangeException @ B_IS_NULL:\r\n" + Part);
                        }
                        string Code = "";
                        foreach (Seisei.Nino.Reader.Column col in tabla.Columns)
                        {
                            if (col.Name.Equals(ColumnName))
                            {
                                if (col.Identity)
                                {
                                    Code = Part.Replace("@B_IS_NULL[@B]" + IsNullable + "|" + NotNullable + "[@EB]", IsNullable);
                                }
                                else
                                {
                                    Code = Part.Replace("@B_IS_NULL[@B]" + IsNullable + "|" + NotNullable + "[@EB]", NotNullable);
                                }
                                return Code;
                            }
                        }
                    }
                    else
                    {
                        throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_IS_NULL:\r\n" + Part);
                    }

                }
                catch (IndexOutOfRangeException)
                {
                    throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_IS_NULL:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_PRIMARY_CODE(string Part, Seisei.Nino.Reader.Table tabla)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_PRIMARY_CODE"))
            {
                try
                {
                    string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_PRIMARY_CODE[@B]", "[@EB]");
                    if (SubTemplate.Length > 0)
                    {
                        string Code = "";
                        foreach (Seisei.Nino.Reader.Column col in tabla.Columns)
                        {
                            if (col.Primary)
                            {
                                Code = Part.Replace("@B_PRIMARY_CODE[@B]" + SubTemplate + "[@EB]", RUN_B_PRIMARY(SubTemplate, col.Name));
                            }
                            return Code;
                        }
                    }
                    else
                    {
                        throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_PRIMARY_CODE:\r\n" + Part);
                    }
                    return Part.Replace("@B_PRIMARY_CODE[@B]" + SubTemplate + "[@EB]", "");
                }
                catch (IndexOutOfRangeException)
                {
                    throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_PRIMARY_CODE:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_FOREIGN_CODE(string Part, Seisei.Nino.Reader.Table tabla)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_FOREIGN_CODE"))
            {
                try
                {
                    string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_FOREIGN_CODE[@B]", "[@EB]");
                    if (SubTemplate.Length > 0)
                    {
                        string Code = "";
                        foreach (Seisei.Nino.Reader.Column col in tabla.Columns)
                        {
                            if (col.Foreign)
                            {
                                Code = Part.Replace("@B_FOREIGN_CODE[@B]" + SubTemplate + "[@EB]", RUN_B_FOREIGN(SubTemplate, col.Name));
                            }
                            return Code;
                        }
                    }
                    else
                    {
                        throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_FOREIGN_CODE:\r\n" + Part);
                    }
                    return Part.Replace("@B_FOREIGN_CODE[@B]" + SubTemplate + "[@EB]", "");
                }
                catch (IndexOutOfRangeException)
                {
                    throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_FOREIGN_CODE:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_IDENTITY_CODE(string Part, Seisei.Nino.Reader.Table tabla)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_IDENTITY_CODE"))
            {
                try
                {
                    string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_IDENTITY_CODE[@B]", "[@EB]");
                    if (SubTemplate.Length > 0)
                    {
                        string Code = "";
                        foreach (Seisei.Nino.Reader.Column col in tabla.Columns)
                        {
                            if (col.Identity)
                            {
                                Code = Part.Replace("@B_IDENTITY_CODE[@B]" + SubTemplate + "[@EB]", RUN_B_IDENTITY(SubTemplate, col.Name));
                            }
                            return Code;
                        }
                    }
                    else
                    {
                        throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_IDENTITY_CODE:\r\n" + Part);
                    }
                    return Part.Replace("@B_IDENTITY_CODE[@B]" + SubTemplate + "[@EB]", "");
                }
                catch (IndexOutOfRangeException)
                {
                    throw new BertaNonEndingLoopException("ERROR: IndexOutOfRangeException @ B_IDENTITY_CODE:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_PRIMARY(string Part, string ColName)
        {
            return Part.Replace("@B_PRIMARY", ColName);
        }

        private static string RUN_B_IDENTITY(string Part, string ColName)
        {
            return Part.Replace("@B_IDENTITY", ColName);
        }

        private static string RUN_B_FOREIGN(string Part, string ColName)
        {
            return Part.Replace("@B_FOREIGN", ColName);
        }

        private static string RUN_B_DEFINE_DATA_TYPES(string Part)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_DEFINE_DATA_TYPES"))
            {
                string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_DEFINE_DATA_TYPES[@B]", "[@EB]");
                DataTypeLoader.CargarArchivoTipoDatos(0, SubTemplate);
                if (SubTemplate.Length > 0)
                {
                    return Part.Replace("@B_DEFINE_DATA_TYPES[@B]" + SubTemplate + "[@EB]", "");
                }
                else
                {
                    throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_DEFINE_DATA_TYPES:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_2DEFINE_DATA_TYPES(string Part)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_2DEFINE_DATA_TYPES"))
            {
                string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_2DEFINE_DATA_TYPES[@B]", "[@EB]");
                DataTypeLoader.CargarArchivoTipoDatos(1, SubTemplate);
                if (SubTemplate.Length > 0)
                {
                    return Part.Replace("@B_2DEFINE_DATA_TYPES[@B]" + SubTemplate + "[@EB]", "");
                }
                else
                {
                    throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_2DEFINE_DATA_TYPES:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_3DEFINE_DATA_TYPES(string Part)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_3DEFINE_DATA_TYPES"))
            {
                string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_3DEFINE_DATA_TYPES[@B]", "[@EB]");
                DataTypeLoader.CargarArchivoTipoDatos(2, SubTemplate);
                if (SubTemplate.Length > 0)
                {
                    return Part.Replace("@B_3DEFINE_DATA_TYPES[@B]" + SubTemplate + "[@EB]", "");
                }
                else
                {
                    throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_3DEFINE_DATA_TYPES:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_4DEFINE_DATA_TYPES(string Part)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_4DEFINE_DATA_TYPES"))
            {
                string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_4DEFINE_DATA_TYPES[@B]", "[@EB]");
                DataTypeLoader.CargarArchivoTipoDatos(3, SubTemplate);
                if (SubTemplate.Length > 0)
                {
                    return Part.Replace("@B_4DEFINE_DATA_TYPES[@B]" + SubTemplate + "[@EB]", "");
                }
                else
                {
                    throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_4DEFINE_DATA_TYPES:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_B_5DEFINE_DATA_TYPES(string Part)
        {
            //Verificar que tenga la etiqueta de inicio y final
            while (Part.Contains("@B_5DEFINE_DATA_TYPES"))
            {
                string SubTemplate = INTERNAL_GET_SUBSTRING_BETWEEN_LABELS(Part, "@B_5DEFINE_DATA_TYPES[@B]", "[@EB]");
                DataTypeLoader.CargarArchivoTipoDatos(4, SubTemplate);
                if (SubTemplate.Length > 0)
                {
                    return Part.Replace("@B_5DEFINE_DATA_TYPES[@B]" + SubTemplate + "[@EB]", "");
                }
                else
                {
                    throw new BertaNeedsParametersException("Faltan parámetros para ejecutar la instrucción @B_5DEFINE_DATA_TYPES:\r\n" + Part);
                }
            }
            return Part;
        }

        private static string RUN_LOOP_TABLE_INTERNAL_LABELS(string Code, int Iteration, Seisei.Nino.Reader.Column columna, Seisei.Nino.Reader.Table Tabla)
        {
            string DataType = Global.DataTypes.GetDataTypeWithNumber(1, columna.DataTypeNumber);
            string DataType2 = Global.DataTypes.GetDataTypeWithNumber(2, columna.DataTypeNumber);
            string DataType3 = Global.DataTypes.GetDataTypeWithNumber(3, columna.DataTypeNumber);
            string DataType4 = Global.DataTypes.GetDataTypeWithNumber(4, columna.DataTypeNumber);
            string DataType5 = Global.DataTypes.GetDataTypeWithNumber(5, columna.DataTypeNumber);
            Code = RUN_B_COLNAME(Code, columna);
            Code = RUN_B_DATATYPE(Code, DataType);
            Code = RUN_B_2DATATYPE(Code, DataType2);
            Code = RUN_B_3DATATYPE(Code, DataType3);
            Code = RUN_B_4DATATYPE(Code, DataType4);
            Code = RUN_B_5DATATYPE(Code, DataType5);
            Code = RUN_B_NINO_DATATYPE(Code, columna.DataType);
            Code = RUN_B_IS_PRIMARY(Code, Tabla, columna.Name);
            Code = RUN_B_IS_IDENTITY(Code, Tabla, columna.Name);
            Code = RUN_B_IS_FOREIGN(Code, Tabla, columna.Name);
            Code = RUN_B_IS_NULL(Code, Tabla, columna.Name);
            if (Code.Contains("@B_HAVE_DATALENGTH"))
            {
                Code = RUN_B_HAVE_DATALENGTH(Code, columna);
            }
            Code = RUN_B_NULL(Code);
            Code = RUN_B_ITERATION(Code, Iteration);
            return Code;
        }
    }
}
